package com.ntd.study.protocol.netty;

import cn.hutool.core.util.StrUtil;
import com.ntd.study.protocol.socket.UtilCollectInterface;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

@Slf4j
public class UtilNettyUdpClient implements UtilCollectInterface {
    NioEventLoopGroup workerGroup = new NioEventLoopGroup();
    private final String host;
    private final int port;
    private final int clientPort;
    private ChannelHandlerContext channelHandlerContext;

    public UtilNettyUdpClient(String host, int port) {
        this(host, port, 0);
    }
    public UtilNettyUdpClient(String host, int port, int clientPort) {
        this.host = host;
        this.port = port;
        this.clientPort = clientPort;
        try {
            init();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        final UtilNettyUdpClient utilNettyTcpClient = new UtilNettyUdpClient("127.0.0.1", 38111);
    }

    public void sendMsg(byte[] bytes){
        sendMsg(bytes, null);
    }

    public void sendMsg(byte[] bytes, String host){
        channelHandlerContext.channel().writeAndFlush(Unpooled.wrappedBuffer(bytes));
        //向网段内的所有机器广播UDP消息。
        final ByteBuf byteBuf = Unpooled.copiedBuffer(new String(bytes), CharsetUtil.UTF_8);
        try {
            DatagramPacket datagramPacket = new DatagramPacket(byteBuf, new InetSocketAddress(host, port));
            if(StrUtil.isNotBlank(host)){
                datagramPacket = new DatagramPacket(byteBuf, new InetSocketAddress(host, port), new InetSocketAddress(host, clientPort));
            }
            channelHandlerContext
                    .writeAndFlush(datagramPacket)
                    .sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void init() throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap
                .group(workerGroup) // 1.指定线程模型
                .channel(NioDatagramChannel.class) // 2.指定 IO 类型为 NIO
                .option(ChannelOption.SO_BROADCAST,true)//允许广播
                .handler(new SimpleChannelInboundHandler<DatagramPacket>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
                        onMsg(msg.content());
                    }
                    @Override
                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                        channelHandlerContext = ctx;
                        initSuccess();
                    }
                });
        Channel ch = bootstrap.bind(clientPort).sync().channel();
    }
    public void initSuccess(){
        sendMsg("客户端发送消息".getBytes());
    }
    public void onMsg(ByteBuf array) {
        log.info(array.toString(CharsetUtil.UTF_8));
    }
    public void close() {
        workerGroup.shutdownGracefully();
    }
}
